wayland: Implement DND icon hotspot API
authorJonas Ådahl <jadahl@gmail.com>
Tue, 8 Dec 2015 10:19:33 +0000 (18:19 +0800)
committerMatthias Clasen <mclasen@redhat.com>
Fri, 11 Dec 2015 14:16:46 +0000 (09:16 -0500)
In Wayland, the hotspot of a DND icon is set using the buffer offset in
wl_buffer.attach. To implement this, add a private API to cause the
next wl_surface.attach to offset the new buffer with a given offset.
Setting a DND icon hotspot sets this offset while also queuing a redraw
of the window to trigger the wl_surface.attach.

https://bugzilla.gnome.org/show_bug.cgi?id=759168

gdk/wayland/gdkdnd-wayland.c
gdk/wayland/gdkprivate-wayland.h
gdk/wayland/gdkwindow-wayland.c

index f20a0e7ab07a7b5b6927f704ddcec1fd95719fc6..fd0d0a3c068af01775aa4e57c1347020ef3aa9cd 100644 (file)
@@ -306,8 +306,20 @@ gdk_wayland_drag_context_set_hotspot (GdkDragContext *context,
                                       gint            hot_x,
                                       gint            hot_y)
 {
-  GDK_WAYLAND_DRAG_CONTEXT (context)->hot_x = hot_x;
-  GDK_WAYLAND_DRAG_CONTEXT (context)->hot_y = hot_y;
+  GdkWaylandDragContext *context_wayland = GDK_WAYLAND_DRAG_CONTEXT (context);
+  gint prev_hot_x = context_wayland->hot_x;
+  gint prev_hot_y = context_wayland->hot_y;
+  const GdkRectangle damage_rect = { .width = 1, .height = 1 };
+
+  context_wayland->hot_x = hot_x;
+  context_wayland->hot_y = hot_y;
+
+  if (prev_hot_x == hot_x && prev_hot_y == hot_y)
+    return;
+
+  _gdk_wayland_window_offset_next_wl_buffer (context_wayland->dnd_window,
+                                             -hot_x, -hot_y);
+  gdk_window_invalidate_rect (context_wayland->dnd_window, &damage_rect, FALSE);
 }
 
 static void
index 00db37f3b18d91acff04267eea4b21572dbedfb5..c4b51856434e39809a52fefc833ad0abe19abebb 100644 (file)
@@ -104,6 +104,10 @@ void            _gdk_wayland_window_register_dnd (GdkWindow *window);
 GdkDragContext *_gdk_wayland_window_drag_begin (GdkWindow *window,
                                                GdkDevice *device,
                                                GList     *targets);
+void            _gdk_wayland_window_offset_next_wl_buffer (GdkWindow *window,
+                                                           int        x,
+                                                           int        y);
+
 GdkDragContext * _gdk_wayland_drop_context_new (struct wl_data_device *data_device);
 void _gdk_wayland_drag_context_set_source_window (GdkDragContext *context,
                                                   GdkWindow      *window);
index 60dfc59c9c8812daa296e286be2f5f18bd27f797..9354c0d350890dad0665e264d581ad5c195051f9 100644 (file)
@@ -121,6 +121,8 @@ struct _GdkWindowImplWayland
   GdkWindow *transient_for;
 
   cairo_surface_t *cairo_surface;
+  int pending_buffer_offset_x;
+  int pending_buffer_offset_y;
 
   gchar *title;
 
@@ -564,7 +566,10 @@ gdk_wayland_window_attach_image (GdkWindow *window)
   /* Attach this new buffer to the surface */
   wl_surface_attach (impl->surface,
                      _gdk_wayland_shm_surface_get_wl_buffer (impl->cairo_surface),
-                     0, 0);
+                     impl->pending_buffer_offset_x,
+                     impl->pending_buffer_offset_y);
+  impl->pending_buffer_offset_x = 0;
+  impl->pending_buffer_offset_y = 0;
 
   /* Only set the buffer scale if supported by the compositor */
   display = GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
@@ -2742,3 +2747,18 @@ gdk_wayland_window_set_dbus_properties_libgtk_only (GdkWindow  *window,
 
   maybe_set_gtk_surface_dbus_properties (window);
 }
+
+void
+_gdk_wayland_window_offset_next_wl_buffer (GdkWindow *window,
+                                           int        x,
+                                           int        y)
+{
+  GdkWindowImplWayland *impl;
+
+  g_return_if_fail (GDK_IS_WAYLAND_WINDOW (window));
+
+  impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
+
+  impl->pending_buffer_offset_x = x;
+  impl->pending_buffer_offset_y = y;
+}